var EXPORTED_SYMBOLS = [ "MLDonkeyProtocolData", "MLDonkeyNetworkFlags", "MLDonkeyNetworkInfo", "MLDonkeyClientStats", "MLDonkeyFileUpdateAvailability", "MLDonkeySharedFileInfo", "MLDonkeyAddress", "MLDonkeyTag", "MLDonkeyConnectionState", "MLDonkeyServerInfo", "MLDonkeyClientKind", "MLDonkeyClientInfo", "MLDonkeyData" ];

Components.utils.import("resource://commons/HashMap.js");

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyProtocolData() {
}

MLDonkeyProtocolData.client = null;
MLDonkeyProtocolData.server = null;
MLDonkeyProtocolData.used = null;

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyNetworkFlags() {
}

// TODO : To edit!!!
MLDonkeyNetworkFlags.prototype.NetworkHasServers = 0;
MLDonkeyNetworkFlags.prototype.NetworkHasRooms = 1;
MLDonkeyNetworkFlags.prototype.NetworkHasMultinet = 2;
MLDonkeyNetworkFlags.prototype.VirtualNetwork = 3;
MLDonkeyNetworkFlags.prototype.NetworkHasSearch = 4;
MLDonkeyNetworkFlags.prototype.NetworkHasChat = 5;
MLDonkeyNetworkFlags.prototype.NetworkHasSupernodes = 6;
MLDonkeyNetworkFlags.prototype.NetworkHasUpload = 7;
MLDonkeyNetworkFlags.prototype.NetworkHasStats = -1;
MLDonkeyNetworkFlags.prototype.UnknownNetworkFlag = -1;

MLDonkeyNetworkFlags.value = null;

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyNetworkInfo(_identifier, _name, _enabled, _configFile, _bytesUploaded, _bytesDownloaded, _connectedServers, _flags) {
	var identifier = _identifier;
	var name = _name;
	var enabled = _enabled;
	var configFile = _configFile;
	var bytesUploaded = _bytesUploaded;
	var bytesDownloaded = _bytesDownloaded;
	var connectedServers = _connectedServers;
	var flags = _flags;

	this.getIdentifier = function() {
		return identifier;
	};
	this.getName = function() {
		return name;
	};
	this.getEnabled = function() {
		return enabled;
	};
	this.getConfigFile = function() {
		return configFile;
	};
	this.getBytesUploaded = function() {
		return bytesUploaded;
	};
	this.getBytesDownloaded = function() {
		return bytesDownloaded;
	};
	this.getConnectedServers = function() {
		return connectedServers;
	};
	this.getFlags = function() {
		return flags;
	};

	this.toString = function() {
		var ret;
		//
		ret = "Network identifier: " + identifier + "\r\n" + "\t             Name: " + name + "\r\n" + "\t          Enabled: " + enabled + "\r\n" + "\t      Config file: " + configFile + "\r\n" + "\t   Bytes uploaded: " + bytesUploaded + "\r\n" + "\t Bytes downloaded: " + bytesDownloaded + "\r\n" + "\tConnected servers: " + connectedServers + "\r\n" + "\t            Flags: " + flags + "\r\n";
		//
		return ret;
	};
}

// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyClientStats() {
	this.toString = function() {
		var ret;
		//
		ret = "Client stats:\r\n" + "\t              Total uploaded: " + this.totalUploaded + "\r\n" + "\t            Total downloaded: " + this.totalDownloaded + "\r\n" + "\t                Total shared: " + this.totalShared + "\r\n" + "\t      Number of shared files: " + this.numberOfSharedFiles + "\r\n" + "\t             Tcp Upload Rate: " + this.tcpUploadRate + "\r\n" + "\t           Tcp Download Rate: " + this.tcpDownloadRate + "\r\n" + "\t             Udp Upload Rate: " + this.udpUploadRate + "\r\n" + "\t           Udp Download Rate: " + this.udpDownloadRate + "\r\n" + "\t Number of current downloads: " + this.numberOfCurrentDownloads + "\r\n" + "\tNumber of downloads finished: " + this.numberOfDownloadsFinished + "\r\n"
		// TODO : + "\tNetworks identifiers, and the corresponding number of
		// connected servers:\r\n"
		// TODO : for(var)
		;
		//
		return ret;
	};
}

MLDonkeyClientStats.prototype.totalUploaded = null;
MLDonkeyClientStats.prototype.totalDownloaded = null;
MLDonkeyClientStats.prototype.totalShared = null;
MLDonkeyClientStats.prototype.numberOfSharedFiles = null;
MLDonkeyClientStats.prototype.tcpUploadRate = null;
MLDonkeyClientStats.prototype.tcpDownloadRate = null;
MLDonkeyClientStats.prototype.udpUploadRate = null;
MLDonkeyClientStats.prototype.udpDownloadRate = null;
MLDonkeyClientStats.prototype.numberOfCurrentDownloads = null;
MLDonkeyClientStats.prototype.numberOfDownloadsFinished = null;
MLDonkeyClientStats.prototype.networkIdentifierToConnectedServersMap = new Array();

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyFileUpdateAvailability() {
	this.toString = function() {
		var ret;
		//
		ret = "File Update Availability:\r\n" + "\t  File number: " + this.fileNumber + "\r\n" + "\tClient number: " + this.clientNumber + "\r\n" + "\t Availability: " + this.availability + "\r\n";
		//
		return ret;
	};
}

MLDonkeyFileUpdateAvailability.prototype.fileNumber = null;
MLDonkeyFileUpdateAvailability.prototype.clientNumber = null;
MLDonkeyFileUpdateAvailability.prototype.availability = null;

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeySharedFileInfo() {
	this.toString = function() {
		var ret;
		//
		ret = "Shared File Info:\r\n" + "\t          Shared File Identifier: " + this.identifier + "\r\n" + "\t              Network Identifier: " + this.networkIdentifier + "\r\n" + "\t                Shared File Name: " + this.fileName + "\r\n" + "\t                       File size: " + this.fileSize + "\r\n" + "\t        Number of Bytes Uploaded: " + this.bytesUploaded + "\r\n" + "\tNumber of Requests for that File: " + this.numOfRequests + "\r\n";
		//
		return ret;
	};
}

MLDonkeySharedFileInfo.prototype.identifier = null;
MLDonkeySharedFileInfo.prototype.networkIdentifier = null;
MLDonkeySharedFileInfo.prototype.fileName = null;
MLDonkeySharedFileInfo.prototype.fileSize = null;
MLDonkeySharedFileInfo.prototype.bytesUploaded = null;
MLDonkeySharedFileInfo.prototype.numOfRequests = null;

// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyAddress() {
	this.readAddress = function(container) {
		this.addressType = container.readInt8();
		if (this.addressType == 0) {
			this.ipAddress = container.readInt32();
			this.geoIP = container.readInt8();
		} else if (this.addressType == 1) {
			this.geoIP = container.readInt8();
			this.nameAddress = container.readString();
		} else {
			throw "Unknown address type";
		}
		this.blocked = container.readInt8();
	};
	this.toString = function() {
		var ret;
		//
		ret = "Address: Address Type: " + this.addressType;
		if (this.addressType == 0) {
			ret += " IP address: " + this.ipAddress;
		} else if (this.addressType == 1) {
			ret += " Name address: " + this.nameAddress;
		}
		ret += " GeoIP: " + this.geoIP + " Blocked: " + this.blocked;
		//
		return ret;
	};
}

MLDonkeyAddress.prototype.addressType = null;
MLDonkeyAddress.prototype.ipAddress = null;
MLDonkeyAddress.prototype.geoIP = null;
MLDonkeyAddress.prototype.nameAddress = null;
MLDonkeyAddress.prototype.blocked = null;

// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyTag() {
	this.readTag = function(container) {
		this.name = container.readString();
		this.type = container.readInt8();
		if ((this.type == 0) || (this.type == 1) || (this.type == 3) || (this.type == 6)) {
			this.tagValue1 = container.readInt32();
		}
		if (this.type == 2) {
			this.tagValue2 = container.readString();
		}
		if (this.type == 4) {
			this.tagValue3 = container.readInt16();
		}
		if (this.type == 5) {
			this.tagValue4 = container.readInt8();
		}
		if (this.type == 6) {
			this.tagValue5 = container.readInt32();
		}
	};

	this.toString = function() {
		var ret;
		//
		ret = "Server Tags:\r\n" + "\t   Tag Name: " + this.name + "\r\n" + "\t   Tag Type: " + this.type + "\r\n";
		if ((this.type == 0) || (this.type == 1) || (this.type == 3) || (this.type == 6)) {
			ret += "\tTag Value 1: " + this.tagValue1 + "\r\n";
		}
		if (this.type == 2) {
			ret += "\tTag Value 2: " + this.tagValue2 + "\r\n";
		}
		if (this.type == 4) {
			ret += "\tTag Value 3: " + this.tagValue3 + "\r\n";
		}
		if (this.type == 5) {
			ret += "\tTag Value 4: " + this.tagValue4 + "\r\n";
		}
		if (this.type == 6) {
			ret += "\tTag Value 5: " + this.tagValue5 + "\r\n";
		}
		//
		return ret;

	};
}

MLDonkeyTag.prototype.name = null;
MLDonkeyTag.prototype.type = null;
MLDonkeyTag.prototype.tagValue1 = null;
MLDonkeyTag.prototype.tagValue2 = null;
MLDonkeyTag.prototype.tagValue3 = null;
MLDonkeyTag.prototype.tagValue4 = null;
MLDonkeyTag.prototype.tagValue5 = null;

// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyConnectionState() {
	this.readConnectionState = function(container) {
		this.connectionState = container.readInt8();
		if ((this.connectionState == 3) || (this.connectionState == 5) || (this.connectionState == 9)) {
			this.rank = container.readInt32();
		}
	};
	this.toString = function() {
		var ret;
		//
		ret = "Connection State: State: " + this.connectionState;
		if ((this.connectionState == 3) || (this.connectionState == 5) || (this.connectionState == 9)) {
			ret += " Rank: " + this.rank;
		}
		//
		return ret;
	};
}

MLDonkeyConnectionState.prototype.connectionState = null;
MLDonkeyConnectionState.prototype.rank = null;

// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyServerInfo() {
	this.toString = function() {
		var ret;
		//
		ret = "Server Info:\r\n" + "\t Server Identifier: " + this.identifier + "\r\n" + "\tNetwork Identifier: " + this.networkIdentifier + "\r\n" + "\t  Internet Address: " + this.internetAddress + "\r\n" + "\t       Server Port: " + this.serverPort + "\r\n" + "\t      Server Score: " + this.serverScore + "\r\n" + "\t   Server Metadata: " + this.serverMetadatas + "\r\n" + "\t    Number of Users: " + this.numberOfUsers + "\r\n" + "\t   Number of Files: " + this.numberOfFiles + "\r\n" + "\t" + this.connectionState + "\r\n" + "\t       Server Name: " + this.serverName + "\r\n" + "\tServer Description: " + this.serverDescription + "\r\n" + "\t         Preferred: " + this.preferred + "\r\n" + "\t    Server Version: " + this.serverVersion + "\r\n" + "\t         Max Users: " + this.maxUsers + "\r\n" + "\t      Low ID Users: " + this.lowIDUsers + "\r\n" + "\t        Soft Limit: " + this.softLimit + "\r\n" + "\t        Hard Limit: " + this.hardLimit + "\r\n" + "\t              Ping: "
				+ this.ping + "\r\n";
		//
		return ret;
	};
}

MLDonkeyServerInfo.prototype.identifier = null;
MLDonkeyServerInfo.prototype.networkIdentifier = null;
MLDonkeyServerInfo.prototype.internetAddress = new MLDonkeyAddress();
MLDonkeyServerInfo.prototype.serverPort = null;
MLDonkeyServerInfo.prototype.serverScore = null;
MLDonkeyServerInfo.prototype.metadata = new Array();
MLDonkeyServerInfo.prototype.numberOfUsers = null;
MLDonkeyServerInfo.prototype.numberOfFiles = null;
MLDonkeyServerInfo.prototype.connectionState = new MLDonkeyConnectionState();
MLDonkeyServerInfo.prototype.serverName = null;
MLDonkeyServerInfo.prototype.serverDescription = null;
MLDonkeyServerInfo.prototype.preferred = null;
MLDonkeyServerInfo.prototype.serverVersion = null;
MLDonkeyServerInfo.prototype.maxUsers = null;
MLDonkeyServerInfo.prototype.lowIDUsers = null;
MLDonkeyServerInfo.prototype.softLimit = null;
MLDonkeyServerInfo.prototype.hardLimit = null;
MLDonkeyServerInfo.prototype.ping = null;

// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyClientKind() {
	this.readKind = function(container) {
		this.type = container.readInt8();
		if (this.type == 1) {
			this.name = container.readString();
			this.hashIdentifier = container.readArrayOfChar(16);
		}
		this.ipAddress = container.readInt32();
		this.geoIP = container.readInt8();
		this.port = container.readInt16();
	};
	this.toString = function() {
		var ret;
		//
		ret = "Client Kind: Type: " + this.type + ((this.type == 1) ? " Name: " + this.name + " Hash Identifier: " + this.hashIdentifier : "") + " IP Address: " + this.ipAddress + " GeoIP: " + this.geoIP + " Port: " + this.port;
		//
		return ret;
	};
}

MLDonkeyClientKind.prototype.type = null;
MLDonkeyClientKind.prototype.name = null;
MLDonkeyClientKind.prototype.hashIdentifier = null;
MLDonkeyClientKind.prototype.ipAddress = null;
MLDonkeyClientKind.prototype.geoIP = null;
MLDonkeyClientKind.prototype.port = null;

// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyClientInfo() {
	this.toString = function() {
		var ret;
		//
		ret = "Client Info:\r\n" + "\t        Identifier: " + this.identifier + "\r\n" + "\tNetwork identifier: " + this.networkIdentifier + "\r\n" + "\t" + this.kind + "\r\n" + "\t" + this.connectionState + "\r\n" + "\t              Type: " + this.type + "\r\n" + "\t          Metadata: " + this.metadata + "\r\n" + "\t              Name: " + this.name + "\r\n" + "\t            Rating: " + this.rating + "\r\n" + "\t          Software: " + this.software + "\r\n" + "\t        Downloaded: " + this.downloaded + "\r\n" + "\t          Uploaded: " + this.uploaded + "\r\n" + "\t   Upload filename: " + this.uploadFileName + "\r\n" + "\t      Connect time: " + this.connectTime + "\r\n" + "\t         eMule mod: " + this.emuleMod + "\r\n" + "\t           Release: " + this.release + "\r\n" + "\t      SUI verified: " + this.suiVerified + "\r\n";
		//
		return ret;
	};
}

MLDonkeyClientInfo.prototype.identifier = null;
MLDonkeyClientInfo.prototype.networkIdentifier = null;
MLDonkeyClientInfo.prototype.kind = new MLDonkeyClientKind();
MLDonkeyClientInfo.prototype.connectionState = new MLDonkeyConnectionState();
MLDonkeyClientInfo.prototype.type = null;
MLDonkeyClientInfo.prototype.metadata = new Array();
MLDonkeyClientInfo.prototype.name = null;
MLDonkeyClientInfo.prototype.rating = null;
MLDonkeyClientInfo.prototype.software = null;
MLDonkeyClientInfo.prototype.downloaded = null;
MLDonkeyClientInfo.prototype.uploaded = null;
MLDonkeyClientInfo.prototype.uploadFileName = null;
MLDonkeyClientInfo.prototype.connectTime = null;
MLDonkeyClientInfo.prototype.emuleMod = null;
MLDonkeyClientInfo.prototype.release = null;
MLDonkeyClientInfo.prototype.suiVerified = null;

// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function MLDonkeyData() {
}

/**
 * 
 */
MLDonkeyData.prototype.protocolData = new MLDonkeyProtocolData();

/**
 * Map of MLDonkeyNetworkInfo.
 * 
 * Key is MLDonkeyNetworkInfo.getIdentifier() and value is MLDonkeyNetworkInfo.
 */
MLDonkeyData.prototype.networksInfo = new Array(/* of MLDonkeyNetworkInfo */);

/**
 * Client stats.
 */
MLDonkeyData.prototype.clientStats = new MLDonkeyClientStats();

/**
 * File update availability;
 */
MLDonkeyData.prototype.fileUpdateAvailability = new MLDonkeyFileUpdateAvailability();

/**
 * Map of MLDonkeySharedFileInfo.
 * 
 * Key is MLDonkeySharedFileInfo.getIdentifier() and value is
 * MLDonkeySharedFileInfo.
 */
MLDonkeyData.prototype.sharedFilesInfo = new Array(/* of MLDonkeySharedFileInfo */);

/**
 * Map of MLDonkeyServerInfo.
 * 
 * Key is MLDonkeyServerInfo.getIdentifier() and value is MLDonkeyServerInfo.
 */
MLDonkeyData.prototype.serversInfo = new HashMap(); // Array(/* of MLDonkeyServerInfo */);

/**
 * Map of MLDonkeyClientInfo.
 * 
 * Key is MLDonkeyClientInfo.getIdentifier() and value is MLDonkeyClientInfo.
 */
MLDonkeyData.prototype.clientsInfo = new Array(/* of MLDonkeyClientInfo */);

/**
 * Map for options.
 * 
 * Option couples is composed by (key, value).
 */
MLDonkeyData.prototype.options = new Array();
